package org.dxy.trigger.http.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dxy.api.dto.request.holiday.GetHolidayDataRequest;
import org.dxy.api.dto.request.holiday.SaveHolidayDataRequest;
import org.dxy.api.dto.request.holiday.BatchSaveHolidayDataRequest;
import org.dxy.api.dto.vo.HolidayDataVo;
import org.dxy.api.dto.vo.HolidayStatisticsVo;
import org.dxy.infrastructure.persistent.po.HolidayPo;
import org.dxy.infrastructure.persistent.service.HolidayService;
import org.dxy.trigger.http.service.HolidayApplicationService;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 假期管理应用服务实现
 * 
 * @author dxy
 * @createTime 2025/9/21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HolidayApplicationServiceImpl implements HolidayApplicationService {
    
    private final HolidayService holidayService;
    
    @Override
    public Map<String, HolidayDataVo> getHolidayData(GetHolidayDataRequest request) {
        log.info("获取假期数据，年月：{}", request.getYearMonth());
        
        // 解析年月
        YearMonth yearMonth = YearMonth.parse(request.getYearMonth());
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();
        
        // 从数据库查询该月的假期数据
        List<HolidayPo> holidayPoList = holidayService.getByDateRange(startDate, endDate);
        
        // 将已有数据转换为Map，方便查找
        Map<LocalDate, HolidayPo> existingDataMap = holidayPoList.stream()
                .collect(Collectors.toMap(HolidayPo::getDate, po -> po));
        
        // 生成该月完整的日期数据
        Map<String, HolidayDataVo> result = new ArrayList<LocalDate>(){{
            for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
                add(date);
            }
        }}.stream().collect(Collectors.toMap(
            date -> date.format(DateTimeFormatter.ISO_LOCAL_DATE),
            date -> {
                HolidayPo existingData = existingDataMap.get(date);
                if (existingData != null) {
                    // 使用数据库中的数据
                    return convertToVo(existingData);
                } else {
                    // 使用默认规则：周一到周五为工作日，周六周日为休息日
                    String defaultType = date.getDayOfWeek().getValue() <= 5 ? "work" : "holiday";
                    return HolidayDataVo.builder()
                            .date(date.format(DateTimeFormatter.ISO_LOCAL_DATE))
                            .type(defaultType)
                            .remark(null)
                            .build();
                }
            }
        ));
        
        return result;
    }
    
    @Override
    public void saveHolidayData(SaveHolidayDataRequest request) {
        log.info("保存假期数据：{}", request);

        LambdaQueryWrapper<HolidayPo> wrapper = new LambdaQueryWrapper<HolidayPo>().eq(HolidayPo::getDate, request.getDate());

        HolidayPo holidayPo = HolidayPo.builder()
                .date(LocalDate.parse(request.getDate()))
                .type(request.getType())
                .remark(request.getRemark())
                .build();

        holidayService.saveOrUpdate(holidayPo,wrapper);
    }
    
    @Override
    public void batchSaveHolidayData(BatchSaveHolidayDataRequest request) {
        log.info("批量保存假期数据，数量：{}", request.getData().size());
        
        List<HolidayPo> holidayPoList = request.getData().stream()
                .map(item -> HolidayPo.builder()
                        .date(LocalDate.parse(item.getDate()))
                        .type(item.getType())
                        .remark(item.getRemark())
                        .build())
                .collect(Collectors.toList());
        
        holidayService.saveBatch(holidayPoList);
    }
    
    @Override
    public void deleteHolidayData(String date) {
        log.info("删除假期数据，日期：{}", date);
        
        holidayService.deleteByDate(LocalDate.parse(date));
    }
    
    @Override
    public HolidayStatisticsVo getHolidayStatistics(Integer year) {
        log.info("获取假期统计数据，年份：{}", year);
        
        // 从数据库获取该年的所有假期数据
        List<HolidayPo> holidayPoList = holidayService.getByYear(year);
        Map<LocalDate, HolidayPo> holidayMap = holidayPoList.stream()
                .collect(Collectors.toMap(HolidayPo::getDate, po -> po));
        
        int totalWorkDays = 0;
        int totalHolidays = 0;
        int customWorkDays = 0;
        int customHolidays = 0;
        
        // 遍历整年的数据进行统计
        LocalDate startDate = LocalDate.of(year, 1, 1);
        LocalDate endDate = LocalDate.of(year, 12, 31);
        
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            HolidayPo holidayData = holidayMap.get(currentDate);
            
            // 判断是否为默认的周末
            boolean isWeekend = currentDate.getDayOfWeek().getValue() >= 6;
            
            if (holidayData != null) {
                if ("work".equals(holidayData.getType())) {
                    totalWorkDays++;
                    if (isWeekend) {
                        customWorkDays++; // 原本是周末但设为工作日
                    }
                } else {
                    totalHolidays++;
                    if (!isWeekend) {
                        customHolidays++; // 原本是工作日但设为休息日
                    }
                }
            } else {
                // 使用默认规则
                if (isWeekend) {
                    totalHolidays++;
                } else {
                    totalWorkDays++;
                }
            }
            
            currentDate = currentDate.plusDays(1);
        }
        
        return HolidayStatisticsVo.builder()
                .year(year)
                .totalWorkDays(totalWorkDays)
                .totalHolidays(totalHolidays)
                .customWorkDays(customWorkDays)
                .customHolidays(customHolidays)
                .build();
    }
    
    /**
     * 转换PO为VO
     */
    private HolidayDataVo convertToVo(HolidayPo po) {
        return HolidayDataVo.builder()
                .date(po.getDate().format(DateTimeFormatter.ISO_LOCAL_DATE))
                .type(po.getType())
                .remark(po.getRemark())
                .build();
    }
}